/* 
 * This file contains utility classes and functions for text block rendering 
 * on the canvas.
 */

// Stores text formatting information.
function TextFormat() {
    this.fontSize = 11;
    this.fontColor = "#000000";
    this.fontFamily = "Tahoma";
    this.isItalic = false;
    this.isBold = false;
    this.isUnderlined = false;
}
// Create string from this format used as value for context.font attribute.
TextFormat.prototype.getFontStyle = function() {
    var s = "";
    s += (this.isBold) ? "bold " : "";
    s += (this.isItalic) ? "italic " : "";
    s += this.fontSize + "px ";
    s += this.fontFamily;
    return s;
};

// ======================== TEXT LINE ========================
// 
// One line of text rendered as part of a block.
function TextLine(text, textFormat) {
    this.text = text;
    this.textFormat = (textFormat !== undefined) ? textFormat : new TextFormat();
    this.textWidth = 0;

    // szukseges meret szamitasa
    canvasCtx.font = this.textFormat.getFontStyle();
    this.textWidth = canvasCtx.measureText(this.text).width;

    this.toString = function() {
        return "[TextLine text='" + this.text + "']";
    };
}


// ======================== BLOCK RENDERER ========================
// 
// One block of a class or interface. Can be:
//  - header box, containing the name and stereotypes of class.
//  - attribute box
//  - method box
//
// Params: 
//  - textLines:            An array of TextLines, containing text information.
//  - hAlign:               Horizontal alignment of the block. 
//                          Possible values: "left", "center"
//  - spacing:              Vertical spacing between two lines 
//  - paddingX,paddingY:    Horizontal and vertical spacing between lines 
//                          and the block wall.
//  - minWidth, minHeight:  Minimum width and height of the block.
//
function BlockRenderer(textLines, hAlign, minWidth, minHeight, paddingX, paddingY, spacing) {


    // ------------ ATTRIBUTES ------------

    this.textLines = textLines;
    this.hAlign = (hAlign !== undefined) ? hAlign : "left";
    this.spacing = (spacing !== undefined) ? spacing : 4;
    this.paddingX = (paddingX !== undefined) ? paddingX : 7;
    this.paddingY = (paddingY !== undefined) ? paddingY : 5;
    this.requiredWidth = 0;
    this.requiredHeight = this.spacing;
    this.minWidth = (minWidth !== undefined) ? minWidth : 50;
    this.minHeight = (minHeight !== undefined) ? minHeight : 15;


    // ------------ CONSTRUCTOR ------------

    // canvas context mentese
    canvasCtx.save();

    for (var i = 0; i < this.textLines.length; i++) {

        this.requiredWidth = Math.max(this.requiredWidth, this.textLines[i].textWidth);

        // magassag novelese
        this.requiredHeight += this.textLines[i].textFormat.fontSize + this.spacing;
    }

    // meg 2*spacing a szelere
    this.requiredWidth = this.requiredWidth + 2 * this.paddingX;
    this.requiredHeight = this.requiredHeight + 2 * this.paddingY - this.spacing; // one more spacing added than needed

    this.requiredWidth = Math.max(this.requiredWidth, this.minWidth);
    this.requiredHeight = Math.max(this.requiredHeight, this.minHeight);

    // canvas context visszaallitasa
    canvasCtx.restore();
}
// Render block with top-left corner at ('posX','posY') and surrounding 
// rectangle of width 'parentWidth'
BlockRenderer.prototype.drawBlock = function(posX, posY, parentWidth) {

    var x = posX + this.paddingX;
    var y = posY + this.paddingY;

    // canvas context mentese
    canvasCtx.save();

    canvasCtx.textBaseline = "middle";

    for (i = 0; i < this.textLines.length; i++) {
        var tl = this.textLines[i];
        var text = tl.text;
        var h = tl.textFormat.fontSize;

        // szukseges magassag szamitasa
        canvasCtx.fillStyle = tl.textFormat.fontColor;
        canvasCtx.font = tl.textFormat.getFontStyle();

        if (this.hAlign === "left") {
            canvasCtx.textAlign = "left";
            canvasCtx.fillText(text, x, y + (h / 2));
        } else if (this.hAlign === "center") {
            canvasCtx.textAlign = "center";
            canvasCtx.fillText(text, x + (parentWidth / 2) - this.paddingX, y + (h / 2));
        }

        if (tl.textFormat.isUnderlined) {
            drawHorizontalLine1px(x, y + h, tl.textWidth, tl.textFormat.fontColor);
        }

        y += h + this.spacing;
    }

    // canvas context visszaallitasa
    canvasCtx.restore();

};
BlockRenderer.prototype.toString = function() {
    return "[BlockRenderer textLines='" + this.textLines + "']";
};


// ======================== MULTI BLOCK RENDERER ========================
// 
// Encapsulates one or more blocks and renders them with the same width.
//
// Params: 
//  - blocks:   An array of BlockRenderers representing one group of blocks.
//
function MultiBlockRenderer(blocks) {

    this.blocks = blocks;
    this.requiredWidth = 0;
    this.requiredHeight = 0;

    for (var i = 0; i < this.blocks.length; i++) {
        this.requiredHeight += this.blocks[i].requiredHeight;
        this.requiredWidth = Math.max(this.requiredWidth, this.blocks[i].requiredWidth);
    }
    this.requiredHeight -= this.blocks.length - 1; // blokkok köze nem 2px széles
}
// Render blocks with top-left corner at pos
MultiBlockRenderer.prototype.drawBlocks = function(pos, fillColor) {
    var x = pos.x;
    var y = pos.y;
    // canvas context mentese
    canvasCtx.save();

    for (var i = 0; i < this.blocks.length; i++) {

        var block = this.blocks[i];
        var w = this.requiredWidth;
        var h = block.requiredHeight;

        // Draw rectangle
        canvasCtx.fillStyle = fillColor;
        canvasCtx.fillRect(x, y, this.requiredWidth, h);
//        canvasCtx.strokeRect(x, y, this.requiredWidth, h);
        drawBox1px(x, y, this.requiredWidth, h, "#000000");

        block.drawBlock(x, y, w);

        y += h - 1;
    }

    // canvas context visszaallitasa
    canvasCtx.restore();

};
MultiBlockRenderer.prototype.toString = function() {
    return "[MultiBlockRenderer blocks='" + this.blocks + "']";
};
